package cn.darkhorse.api.impl;

import cn.darkhorse.api.BusinessTaskDTO;
import cn.darkhorse.api.IActivitiService;
import cn.darkhorse.exception.InteractionFailedException;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.User;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 *
 * @author yuanjun
 * @since 2020/5/28 15:06
 */
@Service
@Slf4j
public class ActivitiServiceDefaultImpl implements IActivitiService {
    @Resource
    private RuntimeService runtimeService;

    @Resource
    private TaskService taskService;

    @Resource
    private IdentityService identityService;


    @Override
    public String startProcessInstanceByKey(String processKey, String businessKey) throws InteractionFailedException {
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processKey, businessKey);
        return processInstance.getId();
    }

    @Override
    public String startProcessInstanceByKey(String processKey, String businessKey, Map<String, Object> variables) throws InteractionFailedException {
        ProcessInstance processInstance = null;
        try {
            processInstance = runtimeService.startProcessInstanceByKey(processKey, businessKey, variables);
        } catch (Exception e) {
            e.printStackTrace();
            String message = e.getMessage();
            if(message.contains("assigneeList is not found")){
                //throw new InteractionFailedException("流程按照岗位形式发起，岗位下无用户审批");
            }else{
                throw new InteractionFailedException("流程发起失败，请联系开发人员！"+e.getMessage());
            }
        }
        return processInstance.getId();
    }

    @Override
    public List<BusinessTaskDTO> queryBusinessTasksByUserName(String userName) throws InteractionFailedException {
        List<Task> taskList = taskService.createTaskQuery()
                .taskCandidateOrAssigned(userName)
                .list();

        List<BusinessTaskDTO> dtoList = getBusinessTaskDtos(taskList);

        if (log.isDebugEnabled()){
            log.debug("当前用户【{}】的任务合计：{} 条", userName, dtoList == null ? "0" :dtoList.size());
        }

        return dtoList;
    }

    @Override
    public List<BusinessTaskDTO> queryBusinessTasksByUserNameAndProcessId(String userName, String processId) throws InteractionFailedException {
        List<Task> taskList = taskService.createTaskQuery()
                .taskCandidateOrAssigned(userName)
                .processInstanceId(processId)
                .list();

        List<BusinessTaskDTO> dtoList = getBusinessTaskDtos(taskList);

        if (log.isDebugEnabled()){
            log.debug("当前用户【{}】的任务合计：{} 条", userName, dtoList == null ? "0" :dtoList.size());
        }

        return dtoList;
    }

    @Override
    public void deleteProcessInstanceById(String processInstanceId, String deleteReason) throws InteractionFailedException {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();

        runtimeService.deleteProcessInstance(processInstanceId,deleteReason);
    }

    @Override
    public Boolean processIsOverById(String processInstanceId) throws InteractionFailedException {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();

        if (null == processInstance) {
            return true;
        }
        
        return false;
    }

    @Override
    public List<BusinessTaskDTO> queryBusinessTasksByGroups(List<String> candidateGroups) throws InteractionFailedException {
        List<Task> taskList = taskService.createTaskQuery()
                .taskCandidateGroupIn(candidateGroups)
                .list();

        List<BusinessTaskDTO> dtoList = getBusinessTaskDtos(taskList);

        if (log.isDebugEnabled()){
            log.debug("当前用户组【%s】的任务合计：%s 条", candidateGroups, dtoList == null ? "0" :dtoList.size());
        }

        return dtoList;
    }

    @Override
    public void agree(String taskId) throws InteractionFailedException {
        taskService.complete(taskId);
    }

    @Override
    public void disagree(String taskId) throws InteractionFailedException {
        String processInstanceId = getProcessInstanceIdByTaskId(taskId);
        runtimeService.deleteProcessInstance(processInstanceId, "disagree");
    }


    @Override
    public void reject(String taskId) throws InteractionFailedException {
        String processInstanceId = getProcessInstanceIdByTaskId(taskId);
        runtimeService.deleteProcessInstance(processInstanceId, "reject");
    }

    @Override
    public void claim(String taskId, String userName) throws InteractionFailedException {
        taskService.claim(taskId,userName);
    }

    @Override
    public void createUser(String userName) throws InteractionFailedException {
        User user = identityService.newUser(userName);
        identityService.saveUser(user);
    }
    
    @Override
    public void deleteUser(String userName) throws InteractionFailedException {
        identityService.deleteUser(userName);
    }
    
    @Override
    public void createGroup(String groupId, String groupName) throws InteractionFailedException {
        //创建组
        Group group = identityService.newGroup(groupId);
        group.setName(groupName);
        identityService.saveGroup(group);
    }
    
    @Override
    public void deleteGroup(String groupId) throws InteractionFailedException {
        identityService.deleteGroup(groupId);
    
    }
    
    @Override
    public void createMemberShip(String userName, String groupId) throws InteractionFailedException {
        identityService.createMembership(userName,groupId);
    }
    
    @Override
    public void deleteMemberShip(String userName, String groupId) throws InteractionFailedException {
        identityService.deleteMembership(userName,groupId);
    }
    
    private List<BusinessTaskDTO> getBusinessTaskDtos(List<Task> taskList) {
        if (taskList.size() == 0) {
            return null;
        }
        List<BusinessTaskDTO> dtoList = new ArrayList<>(taskList.size());
        for (Task task : taskList) {
            String businessKey = runtimeService.createProcessInstanceQuery()
                    .processInstanceId(task.getProcessInstanceId())
                    .singleResult()
                    .getBusinessKey();

            BusinessTaskDTO dto = BusinessTaskDTO.of(task.getId())
                    .setTaskKey(task.getTaskDefinitionKey())
                    .setBusinessKey(businessKey)
                    .setProcessInstanceId(task.getProcessInstanceId());

            dtoList.add(dto);
        }
        return dtoList;
    }

    private String getProcessInstanceIdByTaskId(String taskId) {
        return taskService.createTaskQuery()
                .taskId(taskId)
                .singleResult().getProcessInstanceId();
    }
    
    /**
     * 转办
     * @param taskId
     * @param userName
     * @throws InteractionFailedException
     */
    @Override
    public void transferTask(String taskId, String userName) throws InteractionFailedException {
        taskService.setAssignee(taskId,userName);
    }
    
    
    
}
